/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.fzhucc.modules.activity.service;

import cn.hutool.core.util.RandomUtil;
import com.fzhucc.config.FileProperties;
import com.fzhucc.exception.BadRequestException;
import com.fzhucc.modules.Msg.domain.Msg;
import com.fzhucc.modules.Msg.domain.dto.MsgDto;
import com.fzhucc.modules.Msg.domain.dto.SmallMsgDto;
import com.fzhucc.modules.Msg.repository.MsgRepository;
import com.fzhucc.modules.Msg.service.mapstruct.MsgMapper;
import com.fzhucc.modules.activity.domain.Activity;
import com.fzhucc.modules.activity.domain.ActivityUsers;
import com.fzhucc.modules.activity.domain.dto.*;
import com.fzhucc.modules.activity.repository.ActivityUsersRepository;
import com.fzhucc.modules.activity.repository.ActivityRepository;
import com.fzhucc.modules.activity.service.mapstruct.ActivityMapper;
import com.fzhucc.modules.activity.service.mapstruct.ActivityUsersMapper;
import com.fzhucc.modules.appletBanner.domain.dto.AppletBannerQueryCriteria;
import com.fzhucc.modules.displayMap.domain.dto.DisplayMapQueryCriteria;
import com.fzhucc.modules.fenRecordLog.service.FenRecordLogService;
import com.fzhucc.modules.sciPersonnelInfo.domain.SciPersonnelInfo;
import com.fzhucc.modules.signInRecord.domain.SignInRecord;
import com.fzhucc.modules.signInRecord.repository.SignInRecordRepository;
import com.fzhucc.modules.system.domain.User;
import com.fzhucc.modules.system.domain.UserSmall;
import com.fzhucc.modules.system.repository.UserRepository;
import com.fzhucc.modules.system.repository.UserSmallRepository;
import com.fzhucc.modules.thinktank.domain.Leader;
import com.fzhucc.utils.*;
import io.swagger.annotations.ApiModelProperty;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author yyg
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2022-11-17
 **/
@Service
@RequiredArgsConstructor
public class ActivityService {

    private final ActivityUsersRepository activityUsersRepository;

    private final ActivityRepository activityRepository;

    private final SignInRecordRepository signInRecordRepository;

    private final ActivityMapper activityMapper;

    private final FileProperties properties;

    private final WxClient wxClient;

    private final RedisUtils redisUtils;

    private final ActivityUsersMapper activityUsersMapper;

    private final UserRepository userRepository;

    private final FenRecordLogService fenRecordLogService;

    private final MsgRepository msgRepository;

    private final UserSmallRepository userSmallRepository;

    @Value("${fen.type.hd}")
    public String hd;

    @Value("${org.area.all}")
    public String all;

    @Value("${org.area.all2}")
    public String all2;

    //TODO 根据用户得orgArea 识别保存查询  即区看看区  市看所有包含的区  市看所有市及区

    public Map<String, Object> queryAll(ActivityQueryCriteria criteria, Pageable pageable) {
        //TODO 增加访问分数
        try {
            fenRecordLogService.insertUserFen(hd);
        } catch (Exception e) {

        }
        //fenRecordLogService.insertUserFen(hd);

        if (criteria.getOrgArea() != null && !criteria.getOrgArea().equals("")) {
            //h5的直接传orgArea
            if (criteria.getOrgArea().equals(all)) {
                criteria.setOrgArea(null);
            }
        } else {
            //管理端根据登录用户地区
            criteria.setOrgArea(setCriteria(criteria));
        }
        Page<Activity> page = activityRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<ActivityDto> map = page.map(activityMapper::toDto);
        return PageUtil.toPage(map);
    }

    //根据不同设置不同的部门查看 处理  福建省;  或者  福建省;福州市;   或者 福建省;福州市;马尾区; 这种类型
    public String setCriteria(ActivityQueryCriteria criteria) {
        Long userId = null;
        try {
            userId = SecurityUtils.getCurrentUserId();
        } catch (Exception e) {
            String orgArea = criteria.getOrgArea();
            if (orgArea != null && orgArea.equals(all)) { //如果等于福建省则查全部
                return null;
            } else {
                return orgArea;
            }
        }
        if (userId != null) {
            Optional<User> userOptional = userRepository.findById(userId);
            User res = userOptional.get();
            if (res.getOrgArea() != null && (res.getOrgArea().equals(all) || res.getOrgArea().equals(all2))) {//包含福建省 则查全部
                return null;
            } else {
                if (res.getOrgArea() == null || res.getOrgArea().equals("")) {
                    //不赋予则返回所有都能看
                    return null;
                }
                if (res.getOrgArea().contains(";")) {
                    String[] split = res.getOrgArea().split(";");
                    if (split.length == 2) {
                        return split[1];
                    } else if (split.length == 3) {
                        return split[2]; //因为阶级只到第二级所以只存第二到第二级不存第三级
                    } else if (split.length == 1) {
                        return split[0];
                    } else {
                        throw new BadRequestException("未符合规范的地区区域");
                    }
                } else {
                    throw new BadRequestException("未符合规范的地区区域");
                }
            }
        } else {
            throw new BadRequestException("用户ID未找到");
        }
    }

    public String orgAreaReturn() {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {//未登录则外面传进来
            return "";
        } else {
            Optional<User> userOptional = userRepository.findById(userId);
            User res = userOptional.get();
            if (res.getOrgArea() == null || res.getOrgArea().equals("")) {
                //不赋予则返回所有都能看
                return null;
            }
            if (res.getOrgArea().contains(";")) {
                String[] split = res.getOrgArea().split(";");
                if (split.length == 2) {
                    return split[1];
                } else if (split.length == 3) {
                    return split[1];
                } else if (split.length == 1) {
                    return split[0];
                } else {
                    throw new BadRequestException("未符合规范的地区区域");
                }
            } else {
                throw new BadRequestException("未符合规范的地区区域");
            }
        }
    }

    public List<Activity> queryActivityTop(ActivityWxListQueryCriteria criteria) {
        if (criteria.getOrgArea() == null) {
            return activityRepository.queryTop();
        } else {
            if (criteria.getOrgArea().equals(all)) {
                return activityRepository.queryTop();
            } else {
                return activityRepository.queryTopByOrgArea(criteria.getOrgArea());
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public ActivityIsSignUpDto queryActivityIsSign(Integer id) {
        //TODO 增加访问分数
        try {
            fenRecordLogService.insertUserFen(hd);
        } catch (Exception e) {

        }
        if (!activityRepository.existsById(id)) {
            throw new BadRequestException("活动[id:" + id + "]不存在");
        }
        ActivityIsSignUpDto activityIsSignUpDto = new ActivityIsSignUpDto();
        Long userId = null;
        try {
            userId = SecurityUtils.getCurrentUserId();
        } catch (Exception e) {
        }
        if (userId == null) {
            activityIsSignUpDto.setIsSign(null);
        } else {
            List<ActivityUsers> list = activityUsersRepository.findByActivityIdAndUserId(id, userId);
            if (list != null && list.size() > 0) {
                activityIsSignUpDto.setIsSign(true);
            } else {
                activityIsSignUpDto.setIsSign(false);
            }
        }
        Optional<Activity> res = activityRepository.findById(id);
        activityIsSignUpDto.setActivity(res.get());
        //查询热度 +1
        Integer hot = activityIsSignUpDto.getActivity().getHot();
        activityIsSignUpDto.getActivity().setHot(hot + 1);
        Activity save = activityRepository.save(activityIsSignUpDto.getActivity());
        activityIsSignUpDto.setActivity(save);


        List<Msg> listMsg = msgRepository.findNormalByGlIdWithAuditStatus(res.get().getId(), "审核通过","%活动%");
        if (listMsg != null && listMsg.size() > 0) {
            List<SmallMsgDto> myList = new ArrayList<SmallMsgDto>();
            for (Msg msg : listMsg) {
                SmallMsgDto smallMsgDto = new SmallMsgDto();
                smallMsgDto.setId(msg.getId());
                smallMsgDto.setGlId(msg.getGlId());
                smallMsgDto.setType(msg.getType());
                smallMsgDto.setContext(msg.getContext());
                smallMsgDto.setAuditStatus(msg.getAuditStatus());
                smallMsgDto.setUserId(msg.getUserId());
                smallMsgDto.setUpdateBy(msg.getUpdateBy());
                smallMsgDto.setCreateTime(msg.getCreateTime());
                smallMsgDto.setCreateBy(msg.getCreateBy());
                smallMsgDto.setUpdateTime(msg.getUpdateTime());
                Optional<UserSmall> res2 = userSmallRepository.findById(msg.getUserId());
                if (res2.isPresent()) {
                    smallMsgDto.setUserSmall(res2.get());
                }
                myList.add(smallMsgDto);
            }
            activityIsSignUpDto.setMsgDto(myList);
        }
        return activityIsSignUpDto;
    }

    public List<ActivityUsers> getActivityUsers() {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        List<ActivityUsers> list = activityUsersRepository.queryMyActivity(userId);
        List<ActivityUsersDto> listDto = activityUsersMapper.toDto(list);
        if (listDto != null) {
            for (ActivityUsersDto activityUsersDto : listDto) {
                Optional<Activity> res = activityRepository.findById(activityUsersDto.getActivityId());
                if (res.isPresent()) {
                    Activity activity = res.get();
                    activityUsersDto.setActivity(activity);
                }
            }
        }
        return list;
    }

    public List<ActivityDto> queryAll(ActivityQueryCriteria criteria) {
        if (criteria.getOrgArea() != null && !criteria.getOrgArea().equals("")) {
            //h5的直接传orgArea
            if (criteria.getOrgArea().equals(all)) {
                criteria.setOrgArea(null);
            }
        } else {
            //管理端根据登录用户地区
            criteria.setOrgArea(setCriteria(criteria));
        }
        return activityMapper.toDto(activityRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    public ActivityDto findById(Integer id) {
        //TODO 增加访问分数
        try {
            fenRecordLogService.insertUserFen(hd);
        } catch (Exception e) {

        }

        Activity activity = activityRepository.findById(id).orElseGet(Activity::new);
        ValidationUtil.isNull(activity.getId(), "Activity", "id", id);
        //查询热度 +1
        Integer hot = activity.getHot();
        activity.setHot(hot + 1);
        Activity save = activityRepository.save(activity);
        ActivityDto activityDto = activityMapper.toDto(save);

        List<Msg> listMsg = msgRepository.findNormalByGlIdWithAuditStatus(activityDto.getId(), "审核通过","%活动%");
        if (listMsg != null && listMsg.size() > 0) {
            List<SmallMsgDto> myList = new ArrayList<SmallMsgDto>();
            for (Msg msg : listMsg) {
                SmallMsgDto smallMsgDto = new SmallMsgDto();
                smallMsgDto.setId(msg.getId());
                smallMsgDto.setGlId(msg.getGlId());
                smallMsgDto.setType(msg.getType());
                smallMsgDto.setContext(msg.getContext());
                smallMsgDto.setAuditStatus(msg.getAuditStatus());
                smallMsgDto.setUserId(msg.getUserId());
                smallMsgDto.setUpdateBy(msg.getUpdateBy());
                smallMsgDto.setCreateTime(msg.getCreateTime());
                smallMsgDto.setCreateBy(msg.getCreateBy());
                smallMsgDto.setUpdateTime(msg.getUpdateTime());
                Optional<UserSmall> res = userSmallRepository.findById(msg.getUserId());
                if (res.isPresent()) {
                    smallMsgDto.setUserSmall(res.get());
                }
                myList.add(smallMsgDto);
            }
            activityDto.setMsgDto(myList);
        }
        return activityDto;
    }

    @Transactional(rollbackFor = Exception.class)
    public ActivityDto create(ActivityAddDto activityAddDto) {
        Activity resources = new Activity();
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        resources.setTitle(activityAddDto.getTitle());
        resources.setBanner(activityAddDto.getBanner());
        resources.setReleaseTime(activityAddDto.getReleaseTime());
        resources.setActivityStartTime(activityAddDto.getActivityStartTime());
        resources.setActivityEndTime(activityAddDto.getActivityEndTime());
        resources.setSort(activityAddDto.getSort());
        resources.setHot(0);
        resources.setSponsor(activityAddDto.getSponsor());
        resources.setIntro(activityAddDto.getIntro());
        resources.setContent(activityAddDto.getContent());
        resources.setIsShow(1);
        resources.setSignUpTime(activityAddDto.getSignUpTime());
        resources.setSignEndTime(activityAddDto.getSignEndTime());
        resources.setAddress(activityAddDto.getAddress());
        resources.setReview(activityAddDto.getReview());
        resources.setIsShowSign(0);
        resources.setIsDelete(0);
        resources.setDirect(activityAddDto.getDirect());
        resources.setUndertake(activityAddDto.getUndertake());
        resources.setJointlyDirect(activityAddDto.getJointlyDirect());
        resources.setSustain(activityAddDto.getSustain());
        resources.setGuide(activityAddDto.getGuide());
        resources.setExecutingUnit(activityAddDto.getExecutingUnit());

        if (activityAddDto.getOrgArea()!=null && !activityAddDto.getOrgArea().equals("")){
            resources.setOrgArea(activityAddDto.getOrgArea());
        }else{
            //调整为登录账号为哪个市的添加哪个市
            resources.setOrgArea(orgAreaReturn());
        }

        return activityMapper.toDto(activityRepository.save(resources));
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(ActivityEditDto activityEditDto) {
        Activity resources = new Activity();
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        resources.setId(activityEditDto.getId());
        resources.setTitle(activityEditDto.getTitle());
        resources.setBanner(activityEditDto.getBanner());
        resources.setReleaseTime(activityEditDto.getReleaseTime());
        resources.setActivityStartTime(activityEditDto.getActivityStartTime());
        resources.setActivityEndTime(activityEditDto.getActivityEndTime());
        resources.setSort(activityEditDto.getSort());
        resources.setSponsor(activityEditDto.getSponsor());
        resources.setIntro(activityEditDto.getIntro());
        resources.setContent(activityEditDto.getContent());
        resources.setIsShow(activityEditDto.getIsShow());
        resources.setSignUpTime(activityEditDto.getSignUpTime());
        resources.setSignEndTime(activityEditDto.getSignEndTime());
        resources.setAddress(activityEditDto.getAddress());
        resources.setReview(activityEditDto.getReview());
        resources.setIsShowSign(activityEditDto.getIsShowSign());
        resources.setIsDelete(activityEditDto.getIsDelete());
        resources.setDirect(activityEditDto.getDirect());
        resources.setUndertake(activityEditDto.getUndertake());
        resources.setJointlyDirect(activityEditDto.getJointlyDirect());
        resources.setSustain(activityEditDto.getSustain());
        resources.setGuide(activityEditDto.getGuide());
        resources.setExecutingUnit(activityEditDto.getExecutingUnit());
        if (activityEditDto.getOrgArea()!=null && !activityEditDto.getOrgArea().equals("")){
            resources.setOrgArea(activityEditDto.getOrgArea());
        }else{
            //调整为登录账号为哪个市的添加哪个市
            resources.setOrgArea(orgAreaReturn());
        }

        Activity activity = activityRepository.findById(resources.getId()).orElseGet(Activity::new);
        ValidationUtil.isNull(activity.getId(), "Activity", "id", resources.getId());
        activity.copy(resources);
        activityRepository.save(activity);
    }

    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            //activityRepository.deleteById(id);
            Optional<Activity> res = activityRepository.findById(id);
            if (!res.isPresent()) {
                throw new BadRequestException("未找到活动");
            }
            Activity activity = res.get();
            activity.setIsDelete(1);
            activityRepository.save(activity);
        }
    }

    public void download(List<ActivityDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ActivityDto activity : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("标题", activity.getTitle());
            map.put("banner图片", activity.getBanner());
            map.put("发布时间", activity.getReleaseTime());
            map.put("活动开始时间", activity.getActivityStartTime());
            map.put("活动结束时间", activity.getActivityEndTime());
            map.put("排序", activity.getSort());
            map.put("主办方", activity.getSponsor());
            map.put("简介", activity.getIntro());
            map.put("内容", activity.getContent());
            map.put("是否展示小程序", activity.getIsShow());
            map.put("报名开始时间", activity.getSignUpTime());
            map.put("报名结束时间", activity.getSignEndTime());
            map.put("活动地址", activity.getAddress());
            map.put("活动回顾", activity.getReview());
            map.put("是否展示报名按钮", activity.getIsShowSign());
            map.put("主办", activity.getDirect());
            map.put("承办", activity.getUndertake());
            map.put("协办", activity.getJointlyDirect());
            map.put("支持", activity.getSustain());
            map.put("指导", activity.getGuide());
            map.put("热度", activity.getHot());
            map.put("执行单位", activity.getExecutingUnit());
            map.put("区域划分", activity.getOrgArea());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    public Map<String, String> douploadpic(MultipartFile multipartFile, Integer id) {
        // 文件大小验证
        FileUtil.checkSize(properties.getAvatarMaxSize(), multipartFile.getSize());
        // 验证文件上传的格式
        String image = "gif jpg png jpeg";
        String fileType = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
        if (fileType != null && !image.contains(fileType)) {
            throw new BadRequestException("文件格式错误！, 仅支持 " + image + " 格式");
        }
        Optional<Activity> res = activityRepository.findById(id);
        if (res.isPresent()) {
            Activity activity = res.orElseGet(() -> new Activity());
            String oldPath = activity.getBanner();
            File file = FileUtil.upload(multipartFile, properties.getBanner());
            String path = Objects.requireNonNull(file).getPath();
            String[] files = path.split("file");
            res.get().setBanner("/file" + files[1]);
            activityRepository.save(res.get());
            if (StringUtils.isNotBlank(oldPath)) {
                FileUtil.del(oldPath);
            }
            return new HashMap<String, String>(1) {{
                put("banner", file.getName());
            }};
        }
        return new HashMap<String, String>(1) {{
            put("banner", "fail");
        }};
    }

    public List<SignInRecord> getSignInRecordByActivityId(Integer activityId) {
        if (activityId == null) {
            throw new BadRequestException("活动Id未找到");
        }
        return signInRecordRepository.findByActivityId(activityId);
    }

    /**
     * 生成活动签到记录二维码。绑定码有效时间：1天
     *
     * @param activityId 活动ID
     * @return ActivityBindDto
     */
    public ActivityBindDto generateQrCode(Integer activityId) {
        if (!activityRepository.existsById(activityId)) {
            throw new BadRequestException("活动[id:" + activityId + "]不存在");
        }
        String code = RandomUtil.randomString(10);
        String qrcode = wxClient.generateMpQr(
                null,
                "type=bind&code=" + code
        );
        String url = wxClient.generateUrlLink(
                null,
                "type=bind&code=" + code,
                86400000L
        );
        redisUtils.set("activity:bind:" + code, activityId, 86400);
        ActivityBindDto dto = new ActivityBindDto();
        dto.setExpireTime(86400000L);
        dto.setQrcode(qrcode);
        dto.setUrl(url);
        return dto;
    }

    public String getQRcode(Integer activityId) {
        if (!activityRepository.existsById(activityId)) {
            throw new BadRequestException("活动[id:" + activityId + "]不存在");
        }
        //二维码生成
        String str = wxClient.generateMpQr("pages/activity/activityDetail", activityId.toString());
        return str.replace("\"", "");
    }
}